﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Configuration;
using KC.DataAccess.MV;

namespace KC.Logging
{
	public static class Logger
	{
		public enum Project
		{
			Other = 0,
			KcArchitecture = 1,
			Meta = 2,
			MV = 3
		}
		public enum ErrorLevel {
			Information = 1,
			Warning = 2,
			Error = 3,
			Critical = 4 }

		public static void LogError(Project project, ErrorLevel level, string ex)
		{
			try { LogSql((int)project, (int)level, ex); }
			catch { LogFile((int)project, (int)level, ex); }
		}
		public static void LogHistory(int IPID, string Event, string detail) {
			try
			{
				System.Diagnostics.Debug.WriteLine("Log History | " + IPID.ToString("000000000") + " | Event: " + Event + " | Detail: " + detail);
				using (MV8DataContext dc = new MV8DataContext(ConfigurationManager.ConnectionStrings["MV8"].ConnectionString))
				{
					History hist = new History();
					hist.IPID = IPID;
					hist.Event = Event;
					hist.Detail = detail;
					hist.datetime = DateTime.Now;
					dc.Histories.InsertOnSubmit(hist);
					dc.SubmitChanges();
				}
			}
			catch { } 
		}

		/// <summary>Logs error to SQL.</summary>
		/// <param name="ProjectCode">Project code (see Project enum)</param>
		/// <param name="ErrorLevel">Error level (see ErrorLevel enum)</param>
		/// <param name="exc">Error/Exception message</param>
		private static void LogSql(int ProjectCode, int ErrorLevel, string exc)
		{
			if (ErrorLevel < 0 || ErrorLevel > 255) throw new ArgumentOutOfRangeException("ErrorLevel");
			if (ProjectCode < 0 || ProjectCode > 255) throw new ArgumentOutOfRangeException("ProjectCode");
			
			System.Diagnostics.Debug.WriteLine(exc);
			string StackTrace = Environment.StackTrace;
			using (MV8DataContext dc = new MV8DataContext(ConfigurationManager.ConnectionStrings["MV8"].ConnectionString))
			{
				Error err = new Error();
				err.datetime = DateTime.Now;
				err.Ex = exc;
				err.Location = "";
				err.Severity = (byte)ErrorLevel;
				err.Product = (byte)ProjectCode;
				err.StackTrace = StackTrace;
			}
		}
		/// <summary>Logs error to the log file.</summary>
		/// <param name="ProjectCode">Project code (see Project enum)</param>
		/// <param name="ErrorLevel">Error level (see ErrorLevel enum)</param>
		/// <param name="exc">Error/Exception message</param>
		private static void LogFile(int ProjectCode, int ErrorLevel, string exc)
		{
			string
				LogEntry = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss") + " │ " + ProjectCode.ToString().PadLeft(4) + " │ " + ErrorLevel.ToString().PadLeft(4) + " │ " + exc,
				LogFile = KC.Overhead.Constants.Logging.LogFile;
			if (LogFileManagement.isLogFull()) LogFileManagement.RollLogs();

			try { System.IO.File.AppendAllText(LogFile, LogEntry); }
			catch {
				try { 
					LogFileManagement.RollLogs();
					System.IO.File.AppendAllText(LogFile, LogEntry); }
				catch { // last-ditch effort
					System.Threading.Thread.Sleep(250); // Lazy hack, sometimes works
					System.IO.File.WriteAllText(LogFile, LogEntry); } }
		}
	}
}
